/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package earleyalgorithm;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.Set;

/**
 *
 * @author NGOC
 */
public class EarlyAlgorithm {
    private Grammar grammar;
    private WordCollection wordClass;
    private ArrayList<String> words;
    private ArrayList<Table> tables;

    public EarlyAlgorithm(Grammar grammar, WordCollection wordClass, ArrayList<String> words){
        this.grammar = grammar;
        this.wordClass = wordClass;
        this.words = words;
        this.tables = new ArrayList<Table>();
    }

    /**
     * @return the grammar
     */
    public Grammar getGrammar() {
        return grammar;
    }

    /**
     * @param grammar the grammar to set
     */
    public void setGrammar(Grammar grammar) {
        this.grammar = grammar;
    }

    /**
     * @return the tables
     */
    public ArrayList<Table> getTables() {
        return tables;
    }

    /**
     * @param tables the tables to set
     */
    public void setTables(ArrayList<Table> tables) {
        this.tables = tables;
    }

    /**
     * @return the wordClass
     */
    public WordCollection getWordClass() {
        return wordClass;
    }

    /**
     * @param wordClass the wordClass to set
     */
    public void setWordClass(WordCollection wordClass) {
        this.wordClass = wordClass;
    }

    /**
     * @return the words
     */
    public ArrayList<String> getWords() {
        return words;
    }

    /**
     * @param words the words to set
     */
    public void setWords(ArrayList<String> words) {
        this.words = words;
    }

    /*public ArrayList<DottedRule> produceDottedRule(DottedRule dottedRule, int index){
        if(!dottedRule.isPassive()){
            ArrayList<DottedRule> results = new ArrayList<DottedRule>();
            Set<Rule> rules = grammar.getRules(dottedRule.getLeft());
            Iterator<Rule> itr = rules.iterator();
            while(itr.hasNext()){
                DottedRule r = new DottedRule(dottedRule, 0, index);
                r.addBase(dottedRule);
                results.add(r);
            }
            return results;
        }
        return null;
    }*/

    public ArrayList<DottedRule> produceDottedRule(DottedRule dottedRule, int index){
        if(!dottedRule.isPassive()){
            ArrayList<DottedRule> results = new ArrayList<DottedRule>();
            Set<Rule> rules = grammar.getRules(dottedRule.getActiveCategory());
            Iterator<Rule> itr = rules.iterator();
            while(itr.hasNext()){
                DottedRule r = new DottedRule(itr.next(), index);
                ArrayList<DottedRule> bases = new ArrayList<DottedRule>();
                bases.add(dottedRule);
                r.setBases(bases);
                results.add(r);
            }
            return results;
        }
        return null;
    }


    /*public ArrayList<DottedRule> produceDottedRule(DottedRule dottedRule, int position, int index, HashMap<Category,ArrayList<DottedRule>> map){
        if(!dottedRule.isPassive()){
            ArrayList<DottedRule> results = new ArrayList<DottedRule>();
            Set<Rule> rules = grammar.getRules(dottedRule.getLeft());
            Iterator<Rule> itr = rules.iterator();
            while(itr.hasNext()){
                DottedRule r = new DottedRule(dottedRule, 0, index);
                if(!r.isPassive())
                {
                    if(map.containsKey(r.left)){
                        if(map.get(r.left)
                    }
                }
                r.addBase(dottedRule);
                results.add(r);
            }

            return results;
        }
        return null;
    }*/

    public void produceStartTable(){
        Table tb0 = new Table(0);
        Set<Rule> startRules = grammar.getRules(Grammar.startCategory);
        Iterator<Rule> itr = startRules.iterator();
        while (itr.hasNext()){
            DottedRule dottedRule = new DottedRule(itr.next(), 0);
            tb0.addDottedRule(dottedRule);
        }
        for(int i = 0; i < tb0.getDottedRules().size(); i++){
            DottedRule dottedRule = tb0.getDottedRules().get(i);
            ArrayList<DottedRule> list = produceDottedRule(dottedRule, tb0.getIndex());
            if(list != null) {
                for(int j = 0; j < list.size(); j++){
                    DottedRule infer = list.get(j);
                    if(tb0.getDottedRules().contains(infer)){
                        int k = tb0.getDottedRules().indexOf(infer);
                        tb0.getDottedRules().get(k).addBase(dottedRule);
                    }
                    else {
                        tb0.addDottedRule(infer);
                    }
                }
            }  
        }
        tables.add(tb0);
    }

    public void produceTable(String token, int index){
        Table tb = tables.get(index - 1);
        Table newtb = new Table(index);
        // Tao ra cac luat dua vao token
        ArrayList<DottedRule> rules = tb.getDottedRules(wordClass.getAllClasses(token));
        for(int i = 0; i < rules.size(); i++){
            DottedRule r = DottedRule.advancedDot(rules.get(i));
            newtb.addDottedRule(r);
        }
        //Tao ra cac luat dua vao cac nonterminal
        for(int i = 0; i < newtb.getDottedRules().size(); i++){
            DottedRule dottedRule = newtb.getDottedRules().get(i);
            ArrayList<DottedRule> list = produceDottedRule(dottedRule, newtb.getIndex());
            if(list != null) {
                for(int j = 0; j < list.size(); j++){
                    DottedRule infer = list.get(j);
                    newtb.addDottedRule(infer);
                }
            }
        }

        // Tao ra back tracking
        for(int i = 0; i < newtb.getDottedRules().size(); i++){
            DottedRule dottedRule = newtb.getDottedRules().get(i);
            if(dottedRule.isEnd()){
                ArrayList<DottedRule> bases = dottedRule.getBases();
                if(bases != null){
                    for(int j = 0; j < bases.size(); j++){
                        DottedRule base = DottedRule.advancedDot(bases.get(j));
                        newtb.addDottedRule(base);
                    }
                }
            }
        }

        //Tao ra cac luat dua vao cac nonterminal
        for(int i = 0; i < newtb.getDottedRules().size(); i++){
            DottedRule dottedRule = newtb.getDottedRules().get(i);
            ArrayList<DottedRule> list = produceDottedRule(dottedRule, newtb.getIndex());
            if(list != null) {
                for(int j = 0; j < list.size(); j++){
                    DottedRule infer = list.get(j);
                    newtb.addDottedRule(infer);
                }
            }
        }
        tables.add(newtb);
    }

    /*public void produceStartTable(){
        Table i0 = new Table("0");

        Set<Rule> rules = grammar.getRules(Grammar.startCategory);
        Iterator<Rule> ir = rules.iterator();
        while(ir.hasNext()){
            DottedRule dotted = new DottedRule(ir.next());
            InferredRule infer = new InferredRule(dotted, 0);
            i0.addInferredRule(infer);
        }
        Iterator<InferredRule> inferir = i0.getRules().iterator();
        while(inferir.hasNext()){
            InferredRule infer = inferir.next();
            ArrayList<InferredRule> list = produceInferredRule(infer, 0);
            if(list != null){
                for(int i = 0; i < list.size(); i++){
                    i0.addInferredRule(list.get(i));
                }
            }
        }
        tables.add(i0);
    }*/
}
